package com.dingding.nettyserver.core.scanner;

import java.lang.reflect.Method;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import com.dingding.nettyserver.common.annotion.RequestCommand;
import com.dingding.nettyserver.common.annotion.RequestTarget;
import com.dingding.nettyserver.common.annotion.RequiredLogin;
import com.dingding.nettyserver.core.util.LogKit;

/**
 * handler扫描器<br/>
 * 
 * <p>扫描所有标注有{@link RequestTarget}注解的handler类,并把这些handler中标记有{@link RequestCommand}注解的方法分类,封装为一个命令执行器 {@link Invoker},
 * 把这些命令执行器统一储存到命令执行器的管理者 {@link InvokerHoler} 中存储起来统一管理
 * 
 * @author fengshuonan
 * @date 2016年11月18日 下午7:27:48
 */
@Component
public class HandlerScaner implements BeanPostProcessor {

	/**
	 * @Description spring容器中每个Bean在初始化之前的操作
	 * @author fengshuonan
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * @Description spring容器的每个Bean在初始化之后的回调
	 * @author fengshuonan
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

		Class<? extends Object> clazz = bean.getClass();

		// 获取这个spring bean的所有接口
		Class<?>[] interfaces = clazz.getInterfaces();

		if (interfaces != null && interfaces.length > 0) {

			// 扫描类的所有接口父类
			for (Class<?> interFace : interfaces) {

				// 判断是否为handler接口类(是否接口上标识有注解@RequestTarget)
				RequestTarget socketTarget = interFace.getAnnotation(RequestTarget.class);

				// 如果没有@RequestTarget注解，则不进行处理
				if (socketTarget == null) {
					continue;
				}

				Method[] methods = interFace.getMethods();
				if (methods != null && methods.length > 0) {

					// 找出所有标注有@RequestCommand注解的方法
					for (Method method : methods) {
						RequestCommand socketCommand = method.getAnnotation(RequestCommand.class);

						// 如果没有标注@RequestCommand的方法，不处理
						if (socketCommand == null) {
							continue;
						}

						byte bizType = socketTarget.bizType(); 	// 业务类型
						short module = socketTarget.module(); 	// 模块号
						short cmd = socketCommand.cmd(); 		// 命令号

						if (InvokerHoler.getInvoker(bizType, module, cmd) == null) {

							// 判断这个方法是否有需要先登录
							RequiredLogin requiredLogin = method.getAnnotation(RequiredLogin.class);

							// 默认情况下没有@RequiredLogin，则是需要登录，或者@RequiredLogin(true)，则也是代表需要登录
							if (requiredLogin == null || requiredLogin.value() == true) {
								InvokerHoler.addInvoker(bizType, module, cmd, Invoker.valueOf(method, bean, true));
							} else {
								InvokerHoler.addInvoker(bizType, module, cmd, Invoker.valueOf(method, bean, false));
							}

						} else {
							LogKit.info("重复命令:" + "module:" + module + " " + "cmd：" + cmd);
						}
					}
				}
			}
		}
		return bean;
	}

}
